#pragma once

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <cstdlib>
#include <cstring>
#include "log.hpp"
#include "err.hpp"
class Sock
{
    const static int gback = 32;
    const static int default_val = -1;
    public:
        Sock() :_listensock(default_val)
        {}
        ~Sock()
        {
            if(_listensock != default_val)
                close(_listensock);
        }
        //创建套接字
        void Socket()
        {
            _listensock = socket(PF_INET, SOCK_STREAM, 0);
            if(_listensock < 0)
            {
                logMessage(FATAL, "create socket error");
                exit(SOCKET_ERR);
            }
            else
            {
                logMessage(NORMAL, "cteate socket success sock: %d", _listensock);
            }

        }

        //绑定
        void Bind(uint16_t port)
        {
            struct sockaddr_in local;
            bzero(&local, sizeof(local));
            local.sin_family = PF_INET;
            local.sin_addr.s_addr = INADDR_ANY;
            local.sin_port = htons(port);

            int n = bind(_listensock, (struct sockaddr*)&local, sizeof(local));
            if(n < 0)
            {
                logMessage(FATAL, "bind error");
                exit(BIND_ERR);
            }
            else
            {
                logMessage(NORMAL, "bind success");
            }
        }

        //设置监听状态
        void Listen()
        {
            int n = listen(_listensock, gback);  //设置全链接队列长度
            if(n < 0)
            {
                logMessage(FATAL, "listen error");
                exit(LISTEN_ERR);
            }
            else
            {
                logMessage(NORMAL, "listen success");
            }
        }

        //accept获取链接
        int Accept(std::string* clientip, uint16_t* clientport)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int n = accept(_listensock, (struct sockaddr *)&client, &len);
            if(n < 0)
            {
                logMessage(ERROR, "accept err");
            }
            else
            {
                logMessage(NORMAL, "accept a new link : %d", n);
                *clientip = inet_ntoa(client.sin_addr);
                *clientport = ntohs(client.sin_port);
            }
            return n;
        }
        int fd()
        {
            return _listensock;
        }

    private:
        int _listensock;    
};